#include "PEIncludes.h"

#include "PEAliceSoftArchiveAld.h"

#include "PEFile.h"
#include "PEArchive.h"
#include "PETools.h"

namespace pe
{

	unsigned int UnpackValue(byte* a_Data)
	{
		return (a_Data[0] << 8) | (a_Data[1] << 16) | (a_Data[2] << 24);
	}

	PE_EXPORT int AliceArchiveAldReadHeader(AliceArchiveAldHeader* a_Target, PEStream* a_Stream)
	{
		PEStreamRead(a_Stream, a_Target, sizeof(AliceArchiveAldHeader), 1);

		if (a_Target->packed_toc_length[1] > 0 || a_Target->packed_toc_length[2] > 0)
		{
			return -1;
		}

		return PE_OK;
	}

	PE_EXPORT int AliceArchiveAldReadData(AliceArchiveAld* a_Target, AliceArchiveAldHeader* a_Header, PEStream* a_Stream)
	{
		unsigned int toc_len = UnpackValue(a_Header->packed_toc_length);
		byte* toc_buff = new byte[toc_len];
		PEStreamRead(a_Stream, toc_buff, 1, toc_len);

		a_Target->entries_total = toc_len / 3;
		a_Target->entries = new AliceArchiveAldEntry[a_Target->entries_total];

		AliceArchiveAldEntry* curr = a_Target->entries;
		unsigned int index = 0;

		PEStreamGetPath(a_Stream, &a_Target->path);
		PEStreamGetDir(a_Stream, &a_Target->workingdir);

		byte* src = toc_buff;
		while (1)
		{
			curr->filename = NULL;

			curr->offset = UnpackValue(src);
			if (curr->offset == 0) { break; }
			src += 3;

			PEStreamSeek(a_Stream, curr->offset, SEEK_SET);

			curr->header = new AliceArchiveAldEntryHeader;
			PEStreamRead(a_Stream, curr->header, sizeof(AliceArchiveAldEntryHeader), 1);
			unsigned int bytes_read;
			PEStreamGetBytesRead(a_Stream, &bytes_read);

			if (curr->header->header_length > 32)
			{
				PE_DEBUG("Skipping index %i (header size: %i)", index, curr->header->filename);
				continue;
			}

			//char* target = new char[_MAX_PATH];
			//ReadUTF8String(&target, (byte*)curr->header->filename);

			//PE_STRCLRCPY(curr->filename, curr->header->filename);
			ReadUTF8String(&curr->filename, (byte*)curr->header->filename);

			if (!wcscmp(curr->filename, L""))
			{
				PE_DEBUG("Empty file, skipping.");
				continue;
			}

			curr++;
			index++;			
		}

		a_Target->entries_filled = index;

		return PE_OK;
	}

	PE_EXPORT int AliceArchiveAldToRaw(PEArchiveRaw* a_Target, AliceArchiveAld* a_Archive)
	{
		a_Target->original = new AliceArchiveAld;
		memcpy(a_Target->original, a_Archive, sizeof(AliceArchiveAld));
		a_Target->original_type = eArchiveType_AliceAld;

		PE_WSTRCLRCPY(a_Target->path, a_Archive->path);
		PE_WSTRCLRCPY(a_Target->workingdir, a_Archive->workingdir);

		a_Target->entries_total = a_Archive->entries_filled;
		a_Target->entries = new PEArchiveEntryRaw[a_Target->entries_total];

		for (unsigned int i = 0; i < a_Target->entries_total; i++)
		{
			if (a_Archive->entries[i].filename == NULL) { continue; }

			/*unsigned int len = strlen(a_Archive->entries[i].filename);
			a_Target->entries[i].path = new wchar_t[len + 1];
			memset(a_Target->entries[i].path, 0, (len + 1) * 2);
			for (unsigned int index_path = 0; index_path < len; index_path++)
			{
				a_Target->entries[i].path[index_path] = a_Archive->entries[i].filename[index_path];
			}
			//mbtowc(a_Target->entries[i].path, a_Archive->entries[i].filename, len);*/

			//PE_STRTOWIDE(a_Target->entries[i].path, a_Archive->entries[i].filename);
			PE_WSTRCLRCPY(a_Target->entries[i].path, a_Archive->entries[i].filename);

			a_Target->entries[i].offset = a_Archive->entries[i].offset + a_Archive->entries[i].header->header_length;
			a_Target->entries[i].filesize = a_Archive->entries[i].header->length;

			wchar_t filename[_MAX_PATH];
			unsigned int filename_length;
			GetPatternedPath(filename, &filename_length, "%name%%ext%", a_Target->entries[i].path);

			PE_WSTRCLRCPY(a_Target->entries[i].filename, filename);
		}

		return PE_OK;
	}

}